﻿#region Header
// Copyright 2007-2011, Jerónimo Milea
// 
// This file is part of NetJsWire.
// 
//     NetJsWire is free software: you can redistribute it and/or modify
//     it under the terms of the GNU General Public License as published by
//     the Free Software Foundation, either version 3 of the License, or
//     (at your option) any later version.
// 
//     NetJsWire is distributed in the hope that it will be useful,
//     but WITHOUT ANY WARRANTY; without even the implied warranty of
//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//     GNU General Public License for more details.
// 
//     You should have received a copy of the GNU General Public License
//     along with NetJsWire.  If not, see <http://www.gnu.org/licenses/>.
#endregion
#region Using

using System;
using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.Windows.Forms.Design.Behavior;
using NetJsWire.Lite.Widgets.UI;
using Newtonsoft.Json;

#endregion

namespace NetJsWire.Lite.Designers
{
    public class WindowDesigner : DocumentDesigner
    {
        // References to designer services, for convenience.
        private BehaviorService _behaviorSvc;
        private IComponentChangeService _changeService;
        private Adorner _marginAndPaddingAdorner;
        private ISelectionService _selectionService;
        private Window _window;

        private DesignerVerbCollection m_Verbs;

        // DesignerVerbCollection is overridden from ComponentDesigner
        public override DesignerVerbCollection Verbs
        {
            get
            {
                if ( m_Verbs == null )
                {
                    // Create and initialize the collection of verbs
                    m_Verbs = new DesignerVerbCollection();

                    m_Verbs.Add( new DesignerVerb( "Get JavaScript", OnGetJavaScript ) );
                    m_Verbs.Add( new DesignerVerb( "Get JavaScript class", OnGetJavaScriptClass ) );
                }
                return m_Verbs;
            }
        }

        public override void Initialize( IComponent component )
        {
            _window = component as Window;
            if ( _window == null )
                throw new NotSupportedException( "WindowDesigner can be initialized only with Window." );

            _window.TopLevel = false;
            _window.Visible = true;
            var backColor = _window.BackColor;
            base.Initialize( component );
            _window.BackColor = backColor;
            InitializeServices();
            //InitializeMarginAndPaddingAdorner();

            if ( _selectionService != null )
            {
                // set itself to primary selection
                _selectionService.SetSelectedComponents( new[] { Component } );
            }
        }

        public override bool CanParent( Control control )
        {
            if ( control is Window )
                return false;
            return base.CanParent( control );
        }

        // This utility method connects the designer to various services.
        // These references are cached for convenience.
        private void InitializeServices()
        {
            // Acquire a reference to IComponentChangeService.
            _changeService = GetService( typeof( IComponentChangeService ) ) as IComponentChangeService;

            // Acquire a reference to ISelectionService.
            _selectionService = GetService( typeof( ISelectionService ) ) as ISelectionService;

            // Acquire a reference to BehaviorService.
            _behaviorSvc = GetService( typeof( BehaviorService ) ) as BehaviorService;
        }

        protected override void WndProc( ref Message m )
        {
            Point screenPoint;
            //if ( m.Msg == ( int ) NativeMethods.WindowMessages.WM_NCHITTEST )
            //{
            //    m.Result = new IntPtr( 18 );//HTBORDER
            //    return;
            //}
            // Filter out titlebar clicks
            //
            switch ( ( Native.Msg ) m.Msg )
            {
                case Native.Msg.WM_NCMBUTTONDBLCLK:
                case Native.Msg.WM_NCMBUTTONDOWN:
                case Native.Msg.WM_NCRBUTTONDBLCLK:
                //case Native.Msg.WM_NCRBUTTONDOWN:
                case Native.Msg.WM_NCLBUTTONDBLCLK:
                case Native.Msg.WM_NCLBUTTONDOWN:
                case Native.Msg.WM_NCLBUTTONUP:
                    if ( _selectionService != null )
                    {
                        var lParam = m.LParam.ToInt32();
                        var x = ( lParam << 16 ) >> 16; // lo order word
                        var y = lParam >> 16; // hi order word
                        screenPoint = new Point( x, y );
                        var pt = _window.PointToClient( screenPoint );
                        //MessageBox.Show( string.Format( "X: {0}, Y: {1}", pt.X, pt.Y ) );
                        var button = _window.GetButtonAtPoint( pt );
                        _selectionService.SetSelectedComponents( button == null
                                                                 ? new object[] { Component }
                                                                 : new object[] { button } );
                        // Mark message as handled
                        m.Result = IntPtr.Zero;
                    }
                    else
                    {
                        base.WndProc( ref m );
                    }
                    break;
                case Native.Msg.WM_NCHITTEST:
                    var lParam2 = m.LParam.ToInt32();
                    var x2 = ( lParam2 << 16 ) >> 16; // lo order word
                    var y2 = lParam2 >> 16; // hi order word
                    screenPoint = new Point( x2, y2 );
                    var pt2 = _window.PointToClient( screenPoint );
                    if ( !_window.ClientRectangle.Contains( pt2 ) )
                    {
                        m.Result = new IntPtr( 18 );//HTBORDER
                    }
                    else
                    {
                        base.WndProc( ref m );
                    }
                    break;
                default:
                    base.WndProc( ref m );
                    break;
            }
        }

        //protected void WmNcHitTest( Point pt, ref Message m )
        //{
        //    if ( _window != null && _window.DrawButtonsBar )
        //    {
        //        if ( _window.Buttons.Count > 0 )
        //        {
        //            foreach ( var button in _window.Buttons )
        //            {
        //                if ( button.Bounds.Contains( _window.PointToClient( pt ) ) )
        //                {
        //                    MessageBox.Show( "Found" );
        //                    m.Result = new IntPtr( 18 );//HTBORDER
        //                }
        //            }
        //        }
        //    }
        //}

        protected override void PostFilterEvents( IDictionary events )
        {
            if ( events != null )
            {
                if ( events[ "Click" ] != null )
                    events.Remove( "Click" );
                events.Remove( "BackColorChanged" );
            }

            base.PostFilterEvents( events );
        }

        private void OnGetJavaScript( object sender, EventArgs e )
        {
            Clipboard.SetText( _window.Serialize( Formatting.Indented ) );
            MessageBox.Show( "The JavaScript code is on the clipboard", "System" );
        }

        private void OnGetJavaScriptClass( object sender, EventArgs e )
        {
            Clipboard.SetText( _window.SerializeClass( Formatting.Indented ) );
            MessageBox.Show( "The JavaScript code is on the clipboard", "System" );
        }
    }
}